package com.tools.scanner.ad.impl

import android.app.Activity
import android.os.Handler
import android.os.Looper
import android.view.View
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.AdValue
import com.google.android.gms.ads.AdView
import com.google.android.gms.ads.LoadAdError
import com.tools.scanner.ad.callback.OnAdLoadCallback
import com.tools.scanner.ad.callback.OnAdRewardedCallback
import com.tools.scanner.ad.callback.OnAdShowCallback
import com.tools.scanner.utils.DataReportUtil
import com.tools.scanner.utils.LogUtil

abstract class BaseAdImpl(private val mAdId: String, private val mLocation: String) {

    private var mAdLoadListener: OnAdLoadCallback? = null
    private var mAdShowListener: OnAdShowCallback? = null

    fun setAdLoadListener(listener: OnAdLoadCallback) {
        mAdLoadListener = listener
    }

    fun setAdShowListener(listener: OnAdShowCallback) {
        mAdShowListener = listener
    }

    private fun removeAdLoadListener() {
        mAdLoadListener = null
    }

    private fun removeAdShowListener() {
        mAdShowListener = null
    }

    private var isLoading = false
    private var adSeq = ""
    private var beginLoadTime = 0L
    private val mHandler = Handler(Looper.getMainLooper())

    fun startLoad(adView: AdView? = null) {
        if (isAdAvailable()) {
            notifyAdComplete(state = true, isNoFill = false)
            return
        }

        if (isLoading) {
            notifyAdLoading()
            return
        }

        isLoading = true
        adSeq = DataReportUtil.generateUUID()
        beginLoadTime = System.currentTimeMillis()
        if (this is BannerAdImpl) {
            loadBanner(adView!!, mLocation, mAdId)
        } else {
            beginLoad(mLocation, mAdId)
        }
        DataReportUtil.reportAdLoadBegin(mLocation, mAdId, adSeq)
        notifyAdLoading()
    }

    fun show(activity: Activity) {
        if (!isAdAvailable()) {
            mAdShowListener?.onAdShowFail(mLocation, "no ad location:${mLocation}")
            return
        }
        beginShow(activity, mLocation, mAdId)
    }

    private fun notifyAdComplete(state: Boolean, isNoFill: Boolean) {
        LogUtil.logE("adComplete：adLocation=${mLocation}")
        mAdLoadListener?.onAdComplete(mLocation, state, isNoFill)
        removeAdLoadListener()
    }

    protected fun notifyAdLoading() {
        LogUtil.logE("adLoading：adLocation=${mLocation}")
        mAdLoadListener?.onAdLoading(mLocation)
    }

    protected fun notifyAdPrepareShow() {
        LogUtil.logE("adPrepareShow：adLocation=${mLocation}")
        DataReportUtil.reportAdPrepareShow(mLocation, mAdId, adSeq)
    }

    protected fun notifyAdShow() {
        LogUtil.logE("adShow：adLocation=${mLocation}")
        DataReportUtil.reportAdShow(mLocation, mAdId, adSeq)
        mAdShowListener?.onAdShow(mLocation)
    }

    protected fun notifyClick() {
        LogUtil.logE("adClick：adLocation=${mLocation}")
        DataReportUtil.reportAdClick(mLocation, mAdId, adSeq)
        mAdShowListener?.onAdClicked(mLocation)
    }

    protected fun notifyAdClose() {
        LogUtil.logE("adClose：adLocation=${mLocation}")

        DataReportUtil.reportAdClose(mLocation, mAdId, adSeq)
        mAdShowListener?.onAdDismissed(mLocation)
        removeAdShowListener()
    }

    protected fun notifyShowFail(code: Int, message: String) {
        LogUtil.logE("adShowFail：code=${code},message=${message}")
        DataReportUtil.reportAdShowFail(mLocation, mAdId, adSeq, code, message)
        mAdShowListener?.onAdShowFail(mLocation, message)
        removeAdShowListener()
    }

    protected fun notifyAdPaid(adValue: AdValue) {
        LogUtil.logE("adPaid：location=${mLocation}")
        DataReportUtil.reportAdPaid(mLocation, mAdId, adSeq, adValue)
    }

    protected fun notifyAdLoadEnd(code: Int, message: String, source: String, isSuccess: Boolean) {
        LogUtil.logE("adLoadEnd：adLocation=${mLocation}，errorCode=$code，errorMessage=$message")

        val useTime = System.currentTimeMillis() - beginLoadTime

        DataReportUtil.reportAdLoadEnd(
            mLocation,
            mAdId,
            code,
            message,
            useTime / 1000,
            adSeq,
            source
        )

        isLoading = false
        notifyAdComplete(isSuccess, code == AdRequest.ERROR_CODE_NO_FILL)
    }

    protected fun notifyAdRewarded() {
        LogUtil.logE("adRewarded：location=${mLocation}")
        DataReportUtil.reportAdReward(mLocation, mAdId, adSeq)

        val callback = mAdShowListener
        if (callback is OnAdRewardedCallback) {
            callback.onRewarded()
        }
    }

    open fun loadBanner(adView: AdView, adLocation: String, adId: String) {}

    abstract fun beginLoad(adLocation: String, adId: String)

    abstract fun beginShow(activity: Activity, adLocation: String, adId: String)

    abstract fun getNativeView(): View?

    abstract fun isAdAvailable(): Boolean
}